/**************************************************************************//**
 * @file     uart_transfer.c
 * @version  V1.00
 * @brief    General UART ISP slave Sample file
 *
 * @copyright SPDX-License-Identifier: Apache-2.0
 * @copyright (C) 2023 Nuvoton Technology Corp. All rights reserved.
 *****************************************************************************/

/*!<Includes */
#include <string.h>
#include "serial_port.h"
#include "key_word.h"
#include "NuMicro.h"

#define APROM_BASE             (FMC_APROM_BASE + 0x30000)                      /* APROM test start address */

#define RXBUFSIZE 256
volatile int32_t g_i32pointer = 0;
uint8_t g_u8RecData[RXBUFSIZE] = {0};
uint8_t wakeupKey = 1; 
uint8_t wakeupTime = 10;

//extern int32_t  FMC_Write(uint32_t u32Addr, uint32_t u32Data);
//extern int32_t  FMC_Erase(uint32_t u32PageAddr);

NVT_ITCM void UART4_IRQHandler(void) {
    printf("UART4_IRQHandler \n");
    uint8_t u8InChar = 0xFF;
	
    if (UART_GET_INT_FLAG(UART_PORT, UART_INTSTS_RDAINT_Msk | UART_INTSTS_RXTOINT_Msk))
    {
        while (UART_GET_RX_EMPTY(UART_PORT) == 0)
        {
            u8InChar = UART_READ(UART_PORT);
						printf("%c \n", u8InChar);
            g_u8RecData[g_i32pointer++] = u8InChar;			
        }
    }

    if (UART_PORT->FIFOSTS & (UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_PEF_Msk | UART_FIFOSTS_RXOVIF_Msk))
    {
        UART_ClearIntFlag(UART_PORT, (UART_INTSTS_RLSINT_Msk | UART_INTSTS_BUFERRINT_Msk));
    }
}


int ProgramPage(uint32_t adr, uint32_t sz, uint8_t *buf)
{
    
   
    uint32_t u32Wdata;
		int err = 0;
        
    for (uint16_t num = 0 ; num < sz; num += 4)
    {
        u32Wdata = (buf[num + 0] << 0) | (buf[num + 1] << 8) | (buf[num + 2] << 16) | (buf[num + 3] << 24);
        err = FMC_Write(adr + num, u32Wdata);
	    if(err != 0) break;
    }
    return err;
}




int flash_info_write(uint32_t StartAdress, uint16_t offset, uint8_t *var)
{
	int err= 0 ;

    SYS_UnlockReg();    /* Unlock protected registers */
    FMC_Open();         /* Enable FMC ISP function */
    FMC_ENABLE_AP_UPDATE(); /* Enable FMC APROM update function */

    FMC_Erase(StartAdress);

    err = ProgramPage(StartAdress, offset, (uint8_t *)var);
    printf("flash_info_write data%d %d \n",var[0],var[1]);
    FMC_DISABLE_AP_UPDATE();           /* Disable APROM update. */
    FMC_Close();
    /* Lock protected registers */
    SYS_LockReg();
    return err;
}


void flash_info_read(uint32_t StartAdress, uint16_t offset)
{

    SYS_UnlockReg();
    /* Enable FMC ISP function */
    FMC_Open();

    uint8_t buffer[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; // wakeup word,wakeup time


    uint32_t i;
    uint32_t data;
    uint8_t flag = 0;
    for (i = 0; i < offset; i++)
    {   
        data = FMC_Read(StartAdress+i);
        printf("data %d\n",data);
        if(i == 0){
            if(data>0xFF){
                buffer[0] = 0x01;
                data = 1;
                flag = 1;
            }
            wakeupKey = data;
            buffer[0] = data;
            //printf("data0, %d\n",buffer[0]);
        }else if(i == 4){
            if(data>0xFF){
                buffer[4] = 0x05;
                flag = 1;
                data = 5;
            }
            wakeupTime = data;
            buffer[4] = data;
            //printf("data4, %d\n",buffer[4]);
        }
        i = i+3;
    }
    if(flag == 1){
        uint8_t *pData = buffer;
        flash_info_write(APROM_BASE, 8, (uint8_t *)pData);
    }else{
        FMC_Close();
        /* Lock protected registers */
        SYS_LockReg();
    }
    printf("wakeupKey, %d %d \n",wakeupKey,wakeupTime);
    return;
}



void UART4_Init()
{
	  SYS_UnlockReg();
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init UART                                                                                               */
    /*---------------------------------------------------------------------------------------------------------*/
      /* Enable UART clock */
    CLK_EnableModuleClock(UART4_MODULE);
    /* Select UART4 clock source from HIRC */
    CLK_SetModuleClock(UART4_MODULE, CLK_UARTSEL0_UART4SEL_HIRC, CLK_UARTDIV0_UART4DIV(1));
	
	 /* Reset UART module */
    SYS_ResetModule(SYS_UART4RST);
	
    /* Set PB12 as UART0 RXD and PB13 as UART0 TXD */
    SET_UART4_RXD_PC6();
    SET_UART4_TXD_PC7();
   
    /* Reset UART module */
    UART_Open(UART_PORT, 115200);
    NVIC_SetPriority(UART4_IRQn, 1);
    
    NVIC_EnableIRQ(UART4_IRQn);
	  UART_EnableInt(UART_PORT, UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk);
    
    Timer_Init();

    flash_info_read(APROM_BASE, 8);
}


/*WAKE_WORD str2enum(const char *str) {
    if (strcmp(str, "yes") == 0) return CONNECT;
    if (strcmp(str, "no") == 0) return CONNECTED;
    return -1;
}*/
int str2enum(const char *str) {
    if (strcmp(str, "connect") == 0) return 1;
    else if (strcmp(str, "connected") == 0) return 2;
    else if (strcmp(str, "remote_control") == 0) return 3;
    else if (strcmp(str, "living_room") == 0) return 4;
    else if (strcmp(str, "dining_room") == 0) return 5;
    else if (strcmp(str, "kitchen") == 0) return 6;
    else if (strcmp(str, "bedroom") == 0) return 7;
    else if (strcmp(str, "entrance") == 0) return 8;
    else if (strcmp(str, "stairs") == 0) return 9;
    else if (strcmp(str, "washroom") == 0) return 10;
    else if (strcmp(str, "turn_on_light") == 0) return 11;
    else if (strcmp(str, "turn_off_light") == 0) return 12;
    else if (strcmp(str, "turn_on_the_light") == 0) return 13;
    else if (strcmp(str, "turn_off_the_light") == 0) return 14;
    else if (strcmp(str, "power_on") == 0) return 15;
    else if (strcmp(str, "power_off") == 0) return 16;
    else if (strcmp(str, "brighten") == 0) return 17;
    else if (strcmp(str, "brighten_a_little") == 0) return 18;
    else if (strcmp(str, "dim_a_little") == 0) return 19;
    else if (strcmp(str, "dim") == 0) return 20;
    else if (strcmp(str, "set_to_white") == 0) return 21;
    else if (strcmp(str, "set_to_yellow") == 0) return 22;
    else if (strcmp(str, "set_to_orange") == 0) return 23;
    else if (strcmp(str, "whiten_a_little") == 0) return 24;
    else if (strcmp(str, "orange_a_little") == 0) return 25;
    else if (strcmp(str, "gradually_brighten") == 0) return 26;
    else if (strcmp(str, "gradually_dim") == 0) return 27;
    else if (strcmp(str, "gradually_whiten") == 0) return 28;
    else if (strcmp(str, "gradually_orange") == 0) return 29;
    else if (strcmp(str, "stop") == 0) return 30;
    else if (strcmp(str, "night_light") == 0) return 31;
    else if (strcmp(str, "small_bulb") == 0) return 32;
    else if (strcmp(str, "soft_glow") == 0) return 33;
    else if (strcmp(str, "scene_1") == 0) return 34;
    else if (strcmp(str, "scene_2") == 0) return 35;
    else if (strcmp(str, "scene_3") == 0) return 36;
    else if (strcmp(str, "scene_4") == 0) return 37;
    else if (strcmp(str, "morning_light") == 0) return 38;
    else if (strcmp(str, "daytime_light") == 0) return 39;
    else if (strcmp(str, "family_time") == 0) return 40;
    else if (strcmp(str, "relaxation") == 0) return 41;
    else if (strcmp(str, "set_to_red") == 0) return 42;
    else if (strcmp(str, "set_to_green") == 0) return 43;
    else if (strcmp(str, "set_to_blue") == 0) return 44;
    else if (strcmp(str, "color_loop") == 0) return 45;
    else if (strcmp(str, "stop_color_loop") == 0) return 46;
    else if (strcmp(str, "turn_on_main") == 0) return 47;
    else if (strcmp(str, "turn_off_main") == 0) return 48;
    else if (strcmp(str, "turn_on_side") == 0) return 49;
    else if (strcmp(str, "turn_off_side") == 0) return 50;
    else if (strcmp(str, "brighten_side") == 0) return 51;
    else if (strcmp(str, "dim_side") == 0) return 52;
    else if (strcmp(str, "color_loop_side") == 0) return 53;
    else if (strcmp(str, "stop_side") == 0) return 54;
    else if (strcmp(str, "ceiling_buzzer") == 0) return 55;
    else if (strcmp(str, "turn_on_buzzer") == 0) return 56;
    else if (strcmp(str, "turn_off_buzzer") == 0) return 57;
    else if (strcmp(str, "turn_off_after_5_min") == 0) return 58;
    else if (strcmp(str, "turn_off_after_10_min") == 0) return 59;
    else if (strcmp(str, "turn_off_after_15_min") == 0) return 60;
    else if (strcmp(str, "turn_off_after_30_min") == 0) return 61;
    else if (strcmp(str, "turn_off_after_45_min") == 0) return 62;
    else if (strcmp(str, "turn_off_after_60_min") == 0) return 63;
    else if (strcmp(str, "turn_off_after_1_hour") == 0) return 64;
    else if (strcmp(str, "timer_off") == 0) return 65;
    else if (strcmp(str, "send_id") == 0) return 66;
    else if (strcmp(str, "receive_id") == 0) return 67;
    else if (strcmp(str, "register_device") == 0) return 68;
    else if (strcmp(str, "unregister_device") == 0) return 69;
    else if (strcmp(str, "set_lower_limit") == 0) return 70;
    else if (strcmp(str, "remove_lower_limit") == 0) return 71;
    else if (strcmp(str, "register_to_scene_1") == 0) return 72;
    else if (strcmp(str, "register_to_scene_2") == 0) return 73;
    else if (strcmp(str, "register_to_scene_3") == 0) return 74;
    else if (strcmp(str, "register_to_scene_4") == 0) return 75;
    else if (strcmp(str, "register_to_morning_light") == 0) return 76;
    else if (strcmp(str, "register_to_daytime_light") == 0) return 77;
    else if (strcmp(str, "register_to_family_time") == 0) return 7;
    else if (strcmp(str, "register_to_relaxation") == 0) return 79;
    else if (strcmp(str, "wake_up_5_sec") == 0) return 80;
    else if (strcmp(str, "wake_up_10_sec") == 0) return 81;
    else if (strcmp(str, "wake_up_30_sec") == 0) return 82;
    else if (strcmp(str, "wake_up_1_min") == 0) return 83;
    else if (strcmp(str, "change_to_connect") == 0) return 84;
    else if (strcmp(str, "change_to_connected") == 0) return 85;
    else if (strcmp(str, "change_to_remote_control") == 0) return 86;
    else if (strcmp(str, "change_to_living_room") == 0) return 87;
    else if (strcmp(str, "change_to_dining_room") == 0) return 88;
    else if (strcmp(str, "change_to_kitchen") == 0) return 89;
    else if (strcmp(str, "change_to_bedroom") == 0) return 90;
    else if (strcmp(str, "change_to_entrance") == 0) return 91;
    else if (strcmp(str, "change_to_stairs") == 0) return 92;
    else if (strcmp(str, "change_to_washroom") == 0) return 93;  
    return -1;
}

uint8_t isWakeUp = 0;
uint8_t isWakeUpTime = 0;
uint32_t counter = 0;
void UART4_Write(uint8_t pu8TxBuf[]){
    uint8_t data[256] = {0}; 
    int word = str2enum((char*)pu8TxBuf);
    printf("UART4_Write word %d %d\n",word,wakeupKey);
    if(word == wakeupKey){
        isWakeUp = 1;
        counter = 0;
    }
    if(isWakeUp == 1){
        printf("wakeup the control\n");
        if(word != -1){
            //const char *head="\"iresid":\":";
            uint8_t data[256] = {0};
            sprintf((char *)data, "\"iresid\":%d,",word-1);
            uint32_t dataLength = strlen((char*)data);
            uint32_t bytesSent = UART_Write(UART4, data, dataLength);
            if (bytesSent == dataLength) {
                printf("Data sent successfully!\n");
            } else {
                printf("Error: Only %u bytes sent.\n", bytesSent);
            }
        }

        //change wakeup key and wakeup time
        if(word == 84 && 1 != wakeupKey){
            uint8_t buffer[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
            buffer[0] = 0x01;
            buffer[4] = wakeupTime;
            uint8_t *pData = buffer;
            flash_info_write(APROM_BASE, 8, (uint8_t *)pData);
            wakeupKey = 1;
        }else if(word == 85 && 2 != wakeupKey){
            uint8_t buffer[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
            buffer[0] = 0x02;
            buffer[4] = wakeupTime;
            uint8_t *pData = buffer;
            flash_info_write(APROM_BASE, 8, (uint8_t *)pData);
            wakeupKey = 2;
        }
    }
} 

NVT_ITCM void TIMER0_IRQHandler(void) {
    if (TIMER_GetIntFlag(TIMER0) == 1)
    {
        TIMER_ClearIntFlag(TIMER0);
    }
    //printf("1111\n");
    if(isWakeUp == 1){
       
        counter++;
        if(counter>=wakeupTime){
            isWakeUp = 0;
            counter = 0;
            printf("2222222222222222\n");
        }
    }
    /*uint32_t u32TimeOutCnt = SystemCoreClock;
    while (TIMER_GetIntFlag(TIMER0)){

    }*/
}

void Timer_Init(void) {
    SYS_UnlockReg();
    CLK_SetModuleClock(TMR0_MODULE, CLK_TMRSEL_TMR0SEL_PCLK1, 0); 
    CLK_EnableModuleClock(TMR0_MODULE);
    SYS_LockReg();
    Timer_Config();
}

void Timer_Config(void) {
    TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 1);
    TIMER_EnableInt(TIMER0);
    NVIC_EnableIRQ(TIMER0_IRQn);
    TIMER_Start(TIMER0);
}

/*** (C) COPYRIGHT 2023 Nuvoton Technology Corp. ***/